//Include General
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <netdb.h> 

#include <sys/types.h>
#include <sys/ioctl.h> 
#include <fcntl.h>
#include <unistd.h>
#include <pthread.h>

//Include Specific
#include "drv_socket.h"


// on init les thread de reception 
static void drv_socketInitThread ( drv_socketCallbackHandler cb );
//Thread de reception .
static void* drv_socketReceptThread(void* cb);

//file descriptor
static int socket_server =-1;
//file descriptor
static int socket_client =-1;

							


static void* drv_socketReceptThread(void* cb)
{
	struct sockaddr_in client_addr;
	int still_connect;
	unsigned int client_addr_lenght;

	drv_socketCallbackHandler m_cb = (drv_socketCallbackHandler )cb;
	
	while (1)
	{
		socket_client = accept(socket_server, (struct sockaddr *)&client_addr, &client_addr_lenght);
		if (socket_client < 0) 
		{
			//Client deconnecté
			still_connect = 0;
			close(socket_client);
		}
		else
		{
			//on a un client
			//Client connecté : inet_ntoa(client_addr.sin_addr));
			still_connect = 1;
		}
		while( still_connect )
		{
			int nb_bytes_to_read = 0;
			char buffer_read[1024];
			//on lit la socket on ecrit sur le tube
			nb_bytes_to_read = read(socket_client, buffer_read, 1024);
			if(nb_bytes_to_read > 0)
			{
				m_cb(buffer_read, nb_bytes_to_read);
			}
			else
			{
			}	
		}
	}
	drv_socketClose();
	return 0;
}



static void drv_socketInitThread ( drv_socketCallbackHandler cb )
{	
	pthread_t threard_recept;

	//on init le thread
	pthread_create (&threard_recept, NULL, drv_socketReceptThread, (void *)cb ) ;	
}

int drv_socketWriteBytes( char * buffer )
{
	return write(socket_client, buffer, strlen(buffer) - 1);
}


int drv_socketOpen ( int port_socket_server, drv_socketCallbackHandler cb )
{
	struct sockaddr_in server_addr;
	
	socket_server = socket(AF_INET, SOCK_STREAM, 0);
	if (socket_server < 0) 
	{
		printf("ERROR socket()\n");
	}
	int on = 1;
	setsockopt(socket_server,SOL_SOCKET, SO_REUSEADDR ,&on,sizeof(on));
	server_addr.sin_family = AF_INET;
	server_addr.sin_addr.s_addr = INADDR_ANY;
	server_addr.sin_port = htons(port_socket_server);
	if(bind(socket_server, (struct sockaddr *) &server_addr, sizeof(server_addr))<0)
	{
		printf("ERROR bind()\n");
	}
	
	listen(socket_server,1); // 1=> max clients
	
	//on init le thread
	drv_socketInitThread ( cb );
	

	
	return socket_server;
}

void drv_socketClose ( void )
{
	printf("close tcp\n");
	close(socket_client);
	close(socket_server);
}







